#!/usr/bin/env node
/**
 * Skedule 自动构建脚本 - Node.js版本
 * 
 * 功能：
 * 1. 从根目录 package.json 读取版本号
 * 2. 获取当前编译时间
 * 3. 获取 git commit hash（如果可用）
 * 4. 通过 -ldflags 注入到 Go 程序中
 * 5. 跨平台支持（Windows、Linux、macOS）
 */

const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');

// 解析命令行参数
const args = process.argv.slice(2);

// 过滤出非选项参数（不以--开头的参数）
const nonOptionArgs = args.filter(arg => !arg.startsWith('--') && !arg.startsWith('-'));

const platform = nonOptionArgs[0] || (process.platform === 'win32' ? 'windows' : process.platform === 'darwin' ? 'darwin' : 'linux');
const arch = nonOptionArgs[1] || 'amd64';
const verbose = args.includes('--verbose') || args.includes('-v');
const allPlatforms = args.includes('--all-platforms');
const fromAllPlatforms = args.includes('--from-all-platforms');

// 全平台构建配置
const platformConfigs = [
    { platform: 'windows', arch: 'amd64' },
    { platform: 'windows', arch: '386' },
    { platform: 'windows', arch: 'arm64' },
    { platform: 'linux', arch: 'amd64' },
    { platform: 'linux', arch: 'arm64' },
    { platform: 'darwin', arch: 'amd64' },
    { platform: 'darwin', arch: 'arm64' }
];

// 获取目录路径
const scriptDir = __dirname;
const rootDir = path.dirname(scriptDir);           // 项目根目录
const backendDir = path.join(rootDir, 'backend-go'); // 后端源码目录
const frontendDistDir = path.join(rootDir, 'frontend', 'dist'); // 前端构建输出
const backendFrontendDir = path.join(backendDir, 'dist', 'frontend', 'dist'); // backend-go中的前端目录
const distDir = path.join(rootDir, 'dist');

// 删除目录的递归函数
function removeDir(dirPath) {
    if (fs.existsSync(dirPath)) {
        try {
            fs.rmSync(dirPath, { recursive: true, force: true });
        } catch (err) {
            if (err.code === 'EBUSY' || err.code === 'ENOTEMPTY') {
                warning(`无法删除 ${dirPath}，文件可能被占用`);
                warning('请确保没有正在运行的程序占用dist目录中的文件');
                warning('提示：关闭所有运行中的exe文件，然后重试');
                
                // 尝试删除除exe之外的其他文件
                try {
                    const files = fs.readdirSync(dirPath);
                    for (const file of files) {
                        if (!file.endsWith('.exe')) {
                            const filePath = path.join(dirPath, file);
                            fs.rmSync(filePath, { recursive: true, force: true });
                        }
                    }
                    warning('已清理非exe文件，继续构建...');
                } catch (cleanupErr) {
                    warning('部分文件清理失败，但将继续构建');
                }
            } else {
                throw err;
            }
        }
    }
}

// 如果是全平台构建，递归调用每个平台
if (allPlatforms) {
    info('=== Skedule 全平台构建 ===');
    
    // 清理旧的构建输出
    info('清理旧的构建输出...');
    removeDir(distDir);
    success('构建目录已清理');
    
    log(`开始构建 ${platformConfigs.length} 个平台 (Windows x64/x86/ARM64, Linux x64/ARM64, macOS Intel/Apple Silicon)...`);
    
    let successCount = 0;
    let totalSize = 0;
    
    for (let i = 0; i < platformConfigs.length; i++) {
        const config = platformConfigs[i];
        info(`\n[${i + 1}/${platformConfigs.length}] 构建 ${config.platform}/${config.arch}`);
        
        // 构建命令参数
        const buildArgs = [config.platform, config.arch];
        if (verbose) buildArgs.push('--verbose');
        // 传递全平台构建标志给子进程
        buildArgs.push('--from-all-platforms');
        
        // 执行构建
        const buildCommand = `node "${__filename}" ${buildArgs.join(' ')}`;
        const result = execCommand(buildCommand, { stdio: verbose ? 'inherit' : 'pipe' });
        
        if (result.success) {
            // 计算文件大小
            let outputName = `skedule-${config.platform}-${config.arch}`;
            if (config.platform === 'windows') {
                outputName += '.exe';
            }
            const outputPath = path.join(distDir, outputName);
            
            if (fs.existsSync(outputPath)) {
                const stats = fs.statSync(outputPath);
                const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
                totalSize += stats.size;
                success(`✅ ${config.platform}/${config.arch} 构建成功 (${sizeMB} MB)`);
                successCount++;
            }
        } else {
            error(`❌ ${config.platform}/${config.arch} 构建失败`);
            if (result.error && verbose) {
                error(result.error);
            }
        }
    }
    
    // 总结
    info('\n=== 构建总结 ===');
    success(`成功: ${successCount}/${platformConfigs.length} 个平台`);
    const totalSizeMB = (totalSize / (1024 * 1024)).toFixed(2);
    log(`总大小: ${totalSizeMB} MB`);
    
    if (successCount === platformConfigs.length) {
        success('🎉 全平台构建完成！');
        
        // 显示输出文件
        info('\n--- 构建产物 ---');
        
        // 只显示本次构建生成的文件（带平台信息的文件）
        for (const config of platformConfigs) {
            let fileName = `skedule-${config.platform}-${config.arch}`;
            if (config.platform === 'windows') {
                fileName += '.exe';
            }
            
            const filePath = path.join(distDir, fileName);
            if (fs.existsSync(filePath)) {
                const stats = fs.statSync(filePath);
                const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
                log(`📦 ${fileName} (${sizeMB} MB)`);
            }
        }
    } else {
        error('⚠️ 部分平台构建失败，请检查错误信息');
        process.exit(1);
    }
    
    return;
}

// 颜色输出函数
const colors = {
    cyan: '\x1b[36m',
    green: '\x1b[32m',
    yellow: '\x1b[33m',
    red: '\x1b[31m',
    white: '\x1b[37m',
    reset: '\x1b[0m'
};

function colorLog(message, color = 'white') {
    if (process.platform === 'win32' && !process.env.FORCE_COLOR) {
        // Windows CMD可能不支持颜色，简化输出
        console.log(message);
    } else {
        console.log(`${colors[color]}${message}${colors.reset}`);
    }
}

function log(message) {
    colorLog(message, 'white');
}

function success(message) {
    colorLog(`✅ ${message}`, 'green');
}

function warning(message) {
    colorLog(`⚠️ ${message}`, 'yellow');
}

function error(message) {
    colorLog(`❌ ${message}`, 'red');
}

function info(message) {
    colorLog(message, 'cyan');
}

// 执行命令的安全包装
function execCommand(command, options = {}) {
    try {
        const result = execSync(command, { 
            encoding: 'utf8',
            stdio: verbose ? 'inherit' : 'pipe',
            ...options 
        });
        return { success: true, output: result };
    } catch (err) {
        return { success: false, error: err.message, output: err.stdout };
    }
}

// 检查windres工具是否可用
function checkWindres() {
    const result = execCommand('windres --version', { stdio: 'pipe' });
    return result.success;
}

// 生成Windows图标资源文件
function generateIconResource() {
    const iconPath = path.join(backendDir, 'assets', 'app.ico');
    const rcPath = path.join(backendDir, 'app.rc');
    const sysoPath = path.join(backendDir, 'rsrc.syso');
    
    // 检查图标文件是否存在
    if (!fs.existsSync(iconPath)) {
        warning('图标文件不存在，跳过图标嵌入');
        return false;
    }
    
    // 检查windres工具
    if (!checkWindres()) {
        warning('windres工具不可用，跳过图标嵌入');
        warning('提示：安装MinGW-w64或TDM-GCC来启用图标功能');
        return false;
    }
    
    try {
        // 清理旧文件
        [rcPath, sysoPath].forEach(file => {
            if (fs.existsSync(file)) {
                fs.unlinkSync(file);
            }
        });
        
        // 创建资源脚本文件，使用相对路径
        const rcContent = `IDI_ICON1 ICON "assets/app.ico"`;
        fs.writeFileSync(rcPath, rcContent, { encoding: 'utf8' });
        
        // 使用windres编译资源文件
        const windresCommand = `windres -o "${sysoPath}" "${rcPath}"`;
        const windresResult = execCommand(windresCommand, { 
            cwd: backendDir,
            stdio: 'pipe' 
        });
        
        // 清理临时文件
        if (fs.existsSync(rcPath)) {
            fs.unlinkSync(rcPath);
        }
        
        if (windresResult.success && fs.existsSync(sysoPath)) {
            success('Windows图标资源生成成功');
            return true;
        } else {
            warning('图标资源生成失败，继续无图标构建');
            if (windresResult.error && verbose) {
                warning(`windres错误: ${windresResult.error}`);
            }
            return false;
        }
    } catch (err) {
        warning(`图标资源生成异常: ${err.message}`);
        return false;
    }
}

// 复制目录的递归函数
function copyDir(src, dest) {
    if (!fs.existsSync(dest)) {
        fs.mkdirSync(dest, { recursive: true });
    }
    
    const files = fs.readdirSync(src);
    for (const file of files) {
        const srcPath = path.join(src, file);
        const destPath = path.join(dest, file);
        
        const stat = fs.statSync(srcPath);
        if (stat.isDirectory()) {
            copyDir(srcPath, destPath);
        } else {
            fs.copyFileSync(srcPath, destPath);
        }
    }
}

info('=== Skedule 自动构建脚本 ===');
log(`工作目录: ${rootDir}`);
success(`目标平台: ${platform}/${arch}`);

// 如果不是从全平台构建调用的，清理构建目录
if (!fromAllPlatforms) {
    info('\n--- 清理构建目录 ---');
    removeDir(distDir);
    success('构建目录已清理');
}

// 检查前端构建输出
info('\n--- 检查前端构建 ---');
if (fs.existsSync(frontendDistDir)) {
    success('前端构建输出已存在，跳过前端编译');
} else {
    info('前端构建输出不存在，开始自动编译前端...');
    
    // 自动执行前端编译
    const frontendBuildCommand = process.platform === 'win32' 
        ? 'cd frontend && npm run build' 
        : 'cd frontend && npm run build';
    
    const frontendResult = execCommand(frontendBuildCommand, { 
        cwd: rootDir,
        stdio: verbose ? 'inherit' : 'pipe' 
    });
    
    if (frontendResult.success) {
        success('前端编译完成');
        
        // 再次检查前端构建输出
        if (!fs.existsSync(frontendDistDir)) {
            error('前端编译完成但输出目录不存在，构建失败');
            process.exit(1);
        }
    } else {
        error('前端编译失败');
        if (frontendResult.error && verbose) {
            error(frontendResult.error);
        }
        error('请手动运行: npm run build:frontend');
        process.exit(1);
    }
}

// 复制前端构建输出到backend-go目录
info('复制前端构建输出到后端目录...');
try {
    copyDir(frontendDistDir, backendFrontendDir);
    success('前端文件复制完成');
} catch (err) {
    warning(`前端文件复制失败: ${err.message}`);
}

// 1. 读取版本号
info('\n--- 读取版本信息 ---');
const packageJsonPath = path.join(rootDir, 'package.json');
let version = 'unknown';

try {
    if (fs.existsSync(packageJsonPath)) {
        const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
        version = packageJson.version;
        success(`从 package.json 读取版本: ${version}`);
    } else {
        warning('未找到 package.json，使用默认版本');
    }
} catch (err) {
    warning(`读取 package.json 失败: ${err.message}`);
}

// 2. 获取构建时间
const buildDate = new Date().toLocaleString('sv-SE', { 
    timeZone: 'Asia/Shanghai' 
}).replace('T', ' ');
success(`构建时间: ${buildDate}`);

// 3. 获取 git commit hash
let gitCommit = 'no-git';
const gitResult = execCommand('git rev-parse --short HEAD', { stdio: 'pipe' });
if (gitResult.success && gitResult.output) {
    gitCommit = gitResult.output.trim();
    success(`Git Commit: ${gitCommit}`);
} else {
    warning('Git 信息不可用，使用默认值');
}

// 4. 准备编译参数
const ldflags = [
    `-X 'main.Version=${version}'`,
    `-X 'main.BuildDate=${buildDate}'`,
    `-X 'main.GitCommit=${gitCommit}'`,
    '-s -w'  // 减小文件大小
].join(' ');

info('\n--- 编译信息 ---');
log(`版本号: ${version}`);
log(`构建时间: ${buildDate}`);
log(`Git提交: ${gitCommit}`);

// 5. 设置环境变量和切换目录
process.env.GOOS = platform;
process.env.GOARCH = arch;
process.chdir(backendDir); // 切换到后端源码目录进行编译

info('\n--- 开始编译 ---');

// 6. 确保根目录的 dist 目录存在
if (!fs.existsSync(distDir)) {
    fs.mkdirSync(distDir, { recursive: true });
}

// 7. Windows平台图标处理
let hasIcon = false;
if (platform === 'windows') {
    info('\n--- Windows图标处理 ---');
    hasIcon = generateIconResource();
}

// 8. 确定输出文件名
let outputName = 'skedule';

// 如果是全平台构建、从全平台构建调用、或明确指定了平台参数，则添加平台后缀
const shouldAddSuffix = allPlatforms || fromAllPlatforms || nonOptionArgs.length > 0;

if (shouldAddSuffix) {
    outputName += `-${platform}-${arch}`;
}

if (platform === 'windows') {
    outputName += '.exe';
}

const outputPath = path.join(distDir, outputName);

success(`输出文件: ${outputPath}`);
if (platform === 'windows' && hasIcon) {
    success('✨ 将包含自定义图标');
}

// 9. 执行构建
const buildCommand = `go build -ldflags "${ldflags}" -o "${outputPath}" main.go`;

if (verbose) {
    log(`执行命令: ${buildCommand}`);
}

info('正在编译...');
const buildResult = execCommand(buildCommand);

if (buildResult.success) {
    success('\n编译成功!');
    
    // 显示文件信息
    if (fs.existsSync(outputPath)) {
        const stats = fs.statSync(outputPath);
        const fileSizeMB = (stats.size / (1024 * 1024)).toFixed(2);
        success(`文件大小: ${fileSizeMB} MB`);
        success(`输出路径: ${outputPath}`);
        
        // 测试版本信息
        info('\n--- 验证版本信息 ---');
        const versionResult = execCommand(`"${outputPath}" -version`, { stdio: 'pipe' });
        if (versionResult.success && versionResult.output) {
            log(versionResult.output.trim());
        } else {
            warning('无法验证版本信息');
        }
    }
    
    success('\n🎉 构建完成！');
    
    // 使用示例
    info('\n--- 使用示例 ---');
    log('运行程序:');
    log(`  ${outputPath}`);
    log('查看版本:');
    log(`  ${outputPath} -version`);
    log('启动服务器:');
    log(`  ${outputPath} -mode server`);
    
} else {
    error('\n编译失败!');
    if (buildResult.error) {
        error(buildResult.error);
    }
    if (buildResult.output) {
        error(buildResult.output);
    }
    process.exit(1);
} 